/**
 * @class 工具
 */
class Tools {
    constructor() {
        this._imgs = {}; // 需要加载的图片对象
        this._imgTotal = 0; // 总共需要加载的图片数量
        this._loadnum = 0; // 已经加载的数量
        this._complete = false; // 是否全部加载完成
        this._images = {}; // 加载完,值为Image对象的对象
    }

    /**
     * 添加图片
     * @param  {...any} args - 不定参数,参数个数不限,参数可以是包含图片名字和地址的JSON对象；可以是图片路径字符串；可以是数组，数组元素可以是以上两者
     * @example 允许链式调用，参数中键值对的键名和图片名不能重复，否则后者会覆盖前者
     */
    add(...args) {
        for(let i = 0; i < args.length; i++) {
            let arg = args[i];
            if(typeof arg == 'string') {
                let start = arg.lastIndexOf('/') + 1;
                let key = arg.substr(start).replace(/\.\S+/, '');
                this._imgs[key] = arg;
                this._imgTotal++;
            }
            if(Object.prototype.toString.apply(arg).toLowerCase() == '[object object]') {
                for(let key in arg) {
                    this._imgs[key] = arg[key];
                    this._imgTotal++;
                }
            }
            if(Array.isArray(arg)) {
                this.add(...arg);
            }
        }
        this._complete = false;
        return this;
    }
    
    /**
     * 加载图片
     */
    _loadimg(url) {
        return new Promise((resolve, reject) => {
            let pic = new Image();
            pic.src = url;
            pic.onload = () => {
                this._loadnum++;
                resolve(pic);
            }
            pic.onerror = err => {
                reject(err);
            }
        })
    }

    /**
     * 加载全部图片
     * @return {Promise} - async函数返回promise对象，Promise.then返回布尔值
     */
    async loadImages() {
        let keys = Object.keys(this._imgs);
        for(let i = 0; i < keys.length; i++) {
            let key = keys[i];
            this._images[key] = await this._loadimg(this._imgs[key]);
        }
        if(this._loadnum == this._imgTotal) {
            this._complete = true;
        }
        return this._complete;
    }
    
    /**
     * 获取图片对象
     * @return {Object} 返回包含所有图片对象的对象
     */
    get imgData() {
        return this._images;
    }
}

/**
 * @class 游戏
 */
class Game {
    /**
     * 
     */
    constructor() {
        this.canvas = null;
        this.ctx = null;
        this.w = 0;
        this.h = 0;
        this.year = ''; // 游戏年
        this.moon = ''; // 游戏月
        this.day = ''; // 游戏日
        this.init();
    }

    /**初始化game */
    init() {
        let width = document.documentElement.clientWidth; // screen.availWidth;
        let height = document.documentElement.clientHeight; // screen.availHeight;
        this.w = width - 2;
        this.h = height - 2;
        this.canvas = document.createElement('canvas');
        this.canvas.id = 'main';
        this.canvas.width = this.w;
        this.canvas.height = this.h;
        this.ctx = this.canvas.getContext('2d');
        document.body.appendChild(this.canvas);
    }

    /**
     * 设置年月日
     * @param {String} year - 年
     * @param {String} moon - 月 
     * @param {String} day - 日
     */
    setYMD(year, moon, day) {
        [this.year, this.moon, this.day] = [year, moon, day];
    }

    /**
     * 按图层绘制
     * @param {Layer} layers - Layer的实例
     */
    draw(layers) {
        let { map , character, effect, talk, ui } = layers;
        let ts = obj => {
            if(obj) {
                this.ctx.drawImage(obj.canvas, 0, 0, obj.canvas.width, obj.canvas.height, 0, 0, this.w, this.h);
            }
        }
        this.ctx.clearRect(0, 0, this.w, this.h);
        ts(map);
        ts(character);
        ts(effect);
        ts(talk);
        ts(ui);
    }
}

module.exports = { Tools, Game }